package ext.tianma.bom.service.partQuantity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.rmi.RemoteException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.remoting.support.RemoteAccessor;
import org.springframework.stereotype.Service;

import wt.fc.ObjectReference;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.collections.WTArrayList;
import wt.fc.collections.WTHashSet;
import wt.part.WTPart;
import wt.part.WTPartHelper;
import wt.part.WTPartMaster;
import wt.part.WTPartStandardConfigSpec;
import wt.part.WTPartSubstituteLink;
import wt.part.WTPartUsageLink;
import wt.query.QueryException;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.type.ClientTypedUtility;
import wt.type.TypeDefinitionForeignKey;
import wt.type.TypeDefinitionReference;
import wt.type.Typed;
import wt.type.TypedUtility;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.util.WTPropertyVetoException;
import ext.com.core.CoreUtil;
import ext.com.iba.IBAUtil;
import ext.tianma.bom.eco.BOMHelp;
import ext.tianma.bom.expand.service.MaterielService;
import ext.tianma.bom.util.EnumerationUtil;
import ext.tianma.model.APLQuantity;
import ext.tianma.model.ERPQuantity;
import ext.tianma.number.util.PartUtil;
import ext.tianma.part.AVLMaterial.AVLUtil;
import ext.tianma.part.AVLMaterial.constants.RangeChangeConstants;
import ext.tianma.part.ecn.PartCommandsUtil;
import ext.tianma.part.export.BOMUtil;
import ext.tianma.part.report.searchAPL.service.APLService;
import ext.tianma.part.report.searchAPL.util.APLUtil;
import ext.tianma.project2.util.ProjectUtil;
import ext.tianma.util.TMUtil;

@Service
public class QuantityService extends RemoteAccessor{
	
	public static final String MSG = "msg";
	public static final String CODE = "code";
	public static final String SUCCESS = "success";
	public static final String CODE_SUCCESS = "200";
	public static final String CODE_FAILED = "0";
	
	private static String HTTP = null; 
	private static String HOSTNAME = null;
	private static Map<String, String> map = new LinkedHashMap<String, String>();
	
	private static String APLQUANTITY = "APLQuantity";
	private static String WTPART = "WTPart";
	private static String SPLITVALUE = ";;;qqq";
	
	static {
		try {
			WTProperties props = WTProperties.getLocalProperties();
			HTTP = props.getProperty("wt.webserver.protocol");
			HOSTNAME = props.getProperty("java.rmi.server.hostname");
		} catch (IOException e) {
			e.printStackTrace();
		}
		/**构造map，通过反射获取对象属性
		 * key：反射犯法
		 * value：表格显示名称;;;qqq查询对象类
		 * */
		map.put("id", "序号");
		map.put("getName", "名称" + SPLITVALUE + WTPART);
		map.put("getNumber", "料号" + SPLITVALUE + WTPART);
		map.put("getMaterialType", "材料型号" + SPLITVALUE + WTPART);
		map.put("getRanges", "使用范围" + SPLITVALUE + APLQUANTITY);
		map.put("getQuantity", "用量" + SPLITVALUE + APLQUANTITY);
		map.put("getLevels", "等级" + SPLITVALUE + APLQUANTITY);
		map.put("getStatus", "状况" + SPLITVALUE + APLQUANTITY);
		map.put("getCreatorFullName", "责任人" + SPLITVALUE + WTPART);
	}
	
	public void test1(String number, String quantity) throws JSONException {
		JSONObject data = new JSONObject();
		data.put("userName", "B1902413");
		data.put("date", "2020-10-22 12:20:20");
		
		JSONArray partInfo = new JSONArray();
		JSONObject part = new JSONObject();
		part.put("jobs", "202002101476-199-02");
		part.put("partNumber", "0000000132");
		part.put("view", "Design");
		
		JSONArray children = new JSONArray();
		JSONObject child = new JSONObject();
		child.put("childNumber", number); //0000000002
		child.put("childView", "Design");
		child.put("quantity", quantity);
		child.put("unit", "MM");
		
		children.put(child);
		part.put("children", children);
		
		partInfo.put(part);
		data.put("partInfo", partInfo);
		
		initERPData(data.toString());
	}
	
	public JSONObject initERPData(String params) {
		JSONObject result = null;
		WTHashSet set = new WTHashSet();
		try {
			if(StringUtils.isNotEmpty(params)) {
				JSONObject obj = new JSONObject(params);
				String userName = obj.getString("userName");
				String date = obj.getString("date");
				Timestamp time = TMUtil.getTimestamp(date);
				if(obj.has("partInfo")) {
					JSONArray objInfo = obj.getJSONArray("partInfo");//工单信息
					if(null != objInfo && objInfo.length() > 0) {
						ERPQuantity erp = null;
						Map<String, Object> map = null;
						for(int i = 0 ; i < objInfo.length(); i++) {
							JSONObject partInfo = objInfo.getJSONObject(i);
							String jobs = partInfo.getString("jobs"); //ERP工单号
							String partNumber = partInfo.getString("partNumber"); //成品料号
							String partView = partInfo.getString("view"); //成品视图
							WTPart wtpart = CoreUtil.getWTPartByNumberAndView(partNumber, partView);
							if(null == wtpart) {
								continue;
							}
							if(partInfo.has("children")) {
								JSONArray children = partInfo.getJSONArray("children");
								if(null != children && children.length() > 0) {
									for(int j = 0 ; j < children.length(); j++) {
										erp = new ERPQuantity();
										map = new HashMap<String, Object>();
										JSONObject childrenInfo = children.getJSONObject(j);
										String childNumber = childrenInfo.getString("childNumber"); //子料编码
										String childView = childrenInfo.getString("childView"); //子料视图
										String quantity = childrenInfo.getString("quantity"); //子料用量
										String unit = childrenInfo.getString("unit"); //用量单位
										
										erp.setUserName(userName);
										erp.setPushDate(time);
										erp.setJobs(jobs);
										erp.setPartNumber(partNumber);
										erp.setPartView(partView);
										erp.setChildNumber(childNumber);
										erp.setChildView(childView);
										erp.setQuantity(quantity);
										erp.setUnit(unit);
										set.add(erp);
										
										map.put("childNumber", childNumber);
										map.put("childView", childView);
										map.put("quantity", new BigDecimal(quantity));
										String isSuccess = calcQuantity(wtpart, map, set);
										if(StringUtils.isNotEmpty(isSuccess)) {
											result = respInfo(isSuccess);
										}
									}
								} else {
									result = respInfo("组件料号内容为空");
								}
							} else {
								result = respInfo("传输数据中未包含组件料号信息");
							}
						}
					} else {
						result = respInfo("工单信息内容为空");
					}
				} else {
					result = respInfo("传输数据中未包含工单信息");
				}
			} else {
				result = respInfo("未传送数据");
			}
			
			//没有报错，且存在数据时，入库
			if(null == result) {
				if(set.size() > 0) {
					PersistenceHelper.manager.save(set);
				}
				result = respInfo("");
			}
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (WTPropertyVetoException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 判断是否是指定类型物料
	 * @param partNumber
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月4日
	 */
	private boolean isSoftTypePart(WTPart part, String softType) {
		boolean isSoftTypePart = false;
		String typeName = TypedUtility.getTypeIdentifier(part).getTypename();
		if(typeName.indexOf(softType) > -1) {
			isSoftTypePart = true;
		}
		return isSoftTypePart;
	}
	
	/**
	 * 按材料型号、使用范围统计用量
	 * @param wtpart 成品
	 * @param map 子项集合
	 * @param set
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月4日
	 */
	public String calcQuantity(WTPart wtpart, Map<String, Object> map, WTHashSet set) {
		String result = ""; //默认成功，当执行报错时，为具体错误信息
		try {
			String childNumber = (String) map.get("childNumber");
			String childView = (String) map.get("childView");
			BigDecimal quantity = (BigDecimal) map.get("quantity");
			
			WTPart childPart = CoreUtil.getWTPartByNumberAndView(childNumber, childView);
			if(null != childPart) {
				boolean isRAWMATERIAL = isSoftTypePart(childPart, RangeChangeConstants.RAWMATERIAL); //是否原材料
				if(isRAWMATERIAL) {
					//得到原材料的材料型号、release产地
					String materialType = (String) IBAUtil.getIBAValue(childPart, "MaterialType");
					String releaseSite = (String) IBAUtil.getIBAValue(childPart, "releaseSite");
					
					//根据材料型号、release产地得到APL材料：只会有一条
					WTPart avlPart = getAvlmaterialByParams(materialType, releaseSite);
					if(null != avlPart) {
						//得到成品使用范围：如果匹配不到范围，则不处理
						Map<String, String> rangeMap = getRangeValue(wtpart); //范围
						String level = ""; //当前等级
						String levelTo = ""; //进阶至等级
						String range = "";
						if(null != rangeMap && rangeMap.size() > 0) {
							//根据使用范围、APL材料得到用料表对象
							WTPartMaster master = (WTPartMaster) avlPart.getMasterReference().getObject();
							/**先查询某个料在用量表中是否存在
							 * 1、存在
							 * 		a. 则8大使用范围均存在
							 * 		b. 根据物料、使用范围得到具体的用量，然后累加
							 * 2、不存在
							 * 		则直接按照8大范围创建用量表，用量均为0
							 * */
							JSONObject params = new JSONObject();
							params.put("aplPartNumber", master.getNumber());
							List<APLQuantity> qs = AVLUtil.queryAPLQuantity(params);
							APLQuantity aplQuantity = null;
							range = rangeMap.get("key");
							if(qs.size() > 0) {//存在
								//累加具体范围的用量
								aplQuantity = AVLUtil.getAPLQuantity(master.getPersistInfo().getObjectIdentifier().getId(), range);
								//如果存在，累加，如果不存在，存入用量
								if(null != aplQuantity) {
									String hisQuantity = aplQuantity.getQuantity();
									BigDecimal q = new BigDecimal(hisQuantity).add(quantity);//累计用量值
									aplQuantity.setQuantity(q.toString());
									BigDecimal threshold = QuantityConfig.getQuantity(range, aplQuantity.getLevels()); //得到阈值
									if(q.compareTo(threshold) == 1) {//用量值大于阈值时，需要进阶
										aplQuantity.setPromotion(true);
										levelTo = QuantityConfig.getLevel(range, q); //根据传输的用量得到相应层级
										aplQuantity.setLevelTo(levelTo);
									}
									set.add(aplQuantity);
								}
							} else {//不存在，创建
								result = batchCreateAPLQuantity(master, range, quantity, set);
							}
						}
					}
				}
			}
		} catch (WTException e) {
//			result = "接口异常，请联系系统管理员1";
			result = e.getLocalizedMessage(Locale.getDefault());
			e.printStackTrace();
		} catch (RemoteException e) {
//			result = "接口异常，请联系系统管理员2";
			result = e.getLocalizedMessage();
			e.printStackTrace();
		} catch (WTPropertyVetoException e) {
//			result = "接口异常，请联系系统管理员3";
			result = e.getLocalizedMessage(Locale.getDefault());
			e.printStackTrace();
		} catch (JSONException e) {
//			result = "接口异常，请联系系统管理员4";
			result = e.getLocalizedMessage();
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 批量创建APL用量表
	 * @param master
	 * @param range
	 * @param quantity
	 * @param set
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月30日
	 */
	public static String batchCreateAPLQuantity(WTPartMaster master, String range, BigDecimal quantity, WTHashSet set) {
		String level = "L0";//首次进来是Na
		String tip = "";
		try {
			for(int i = 0 ; i < RangeChangeConstants.USABLERANGES.length; i++) {
				APLQuantity aplQuantity = APLQuantity.newAPLQuantity();
				//根据使用范围 +用量(新用量)，得到等级
				BigDecimal threshold = QuantityConfig.getQuantity(RangeChangeConstants.USABLERANGES[i], level); //得到阈值
				if(RangeChangeConstants.USABLERANGES[i].equals(range)) {
					aplQuantity.setQuantity(quantity.toString());
					if(quantity.compareTo(threshold) == 1) {//用量值大于LV0的阈值时，需要进阶
						aplQuantity.setPromotion(true);
						String levelTo = QuantityConfig.getLevel(RangeChangeConstants.USABLERANGES[i], quantity); //根据传输的用量得到相应层级
						aplQuantity.setLevelTo(levelTo);
					} else {
						aplQuantity.setPromotion(false);
						aplQuantity.setLevelTo(level);
					}
				} else {
					aplQuantity.setQuantity("0");
					aplQuantity.setPromotion(false);
					aplQuantity.setLevelTo(level);
				}
				
				aplQuantity.setPersistable(ObjectReference.newObjectReference(master));
				aplQuantity.setProcesses(false);
				aplQuantity.setRanges(RangeChangeConstants.USABLERANGES[i]);
				aplQuantity.setStatus(RangeChangeConstants.STATUS[0]);
				aplQuantity.setLevels(level);
				set.add(aplQuantity);
			}
		} catch (WTPropertyVetoException e) {
			e.printStackTrace();
			tip = e.getLocalizedMessage(Locale.getDefault());
		} catch (WTException e) {
			e.printStackTrace();
			tip = e.getLocalizedMessage(Locale.getDefault());
		}
		return tip;
	}
	
	/**
	 * 根据材料型号、release产地得到APL材料：APL材料只会有一个
	 * @param materialType
	 * @author xucr
	 * @CreateDate 2020年11月4日
	 */
	private WTPart getAvlmaterialByParams(String materialType, String releaseSite) {
		WTPart part = null;
		try {
			QuerySpec qs = new QuerySpec(WTPart.class);
		    qs.setAdvancedQueryEnabled(true);
		    
		    //仅查询APL材料
			TypeDefinitionReference clientType = ClientTypedUtility.getTypeDefinitionReference(RangeChangeConstants.AVLMATERIAL);
			SearchCondition sc = new SearchCondition(WTPart.class,
					Typed.TYPE_DEFINITION_REFERENCE + "." + TypeDefinitionReference.KEY + "." + TypeDefinitionForeignKey.BRANCH_ID, 
					SearchCondition.EQUAL, clientType.getKey().getBranchId());
			qs.appendWhere(sc, new int[] { 0 });
			
			//材料型号：MaterialType， release产地：releaseSite
			Hashtable<String, Object> maramsMap = new Hashtable<>();
			maramsMap.put("MaterialType", materialType);
			maramsMap.put("releaseSite", releaseSite);
			APLUtil.addIBAStringCondition(WTPart.class, qs, maramsMap, SearchCondition.EQUAL, "", false);
			
			//最新小版本
			qs.appendAnd();
			SearchCondition sc1 = new SearchCondition(WTPart.class,"iterationInfo.latest", SearchCondition.IS_TRUE, true);
			qs.appendWhere(sc1, new int[] { 0 });
			
			//最新大版本
			APLService.addSearchConditionLasterVersion(qs, WTPart.class,null);
			
			logger.info(materialType + "对应的SQL：" + qs.toString());
			QueryResult qr = PersistenceHelper.manager.find(qs);
//			qr = new LatestConfigSpec().process(qr);
			while(qr.hasMoreElements()) {
				Object [] obj = (Object[]) qr.nextElement();
				part = (WTPart) obj[0];
			}
		} catch (QueryException e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return part;
	}
	
	public void getBOM(String partNumber, String view, BigDecimal quantity) {
		/**
		 * 1、得到成品
		 * 2、得到子项-->子项-->子项
		 * 3、得到子项使用关系，得到用量
		 * 
		 * */
		
		try {
			WTPart part = CoreUtil.getWTPartByNumberAndView(partNumber, view);
			String version = BOMUtil.getVersion(part);
			
			
		} catch (WTException e) {
			e.printStackTrace();
		}
	}
	
	
	
	/**
	 * 返回内容
	 * @param msg
	 * @return
	 * @throws JSONException
	 * @author xucr
	 * @CreateDate 2020年11月5日
	 */
	private JSONObject respInfo(String msg) throws JSONException {
		JSONObject result = new JSONObject();
		if(StringUtils.isNotEmpty(msg)) {
			result.put(MSG, msg);
			result.put(SUCCESS, false);
			result.put(CODE, CODE_FAILED);
		} else {
			result.put(MSG, "");
			result.put(SUCCESS, true);
			result.put(CODE, CODE_SUCCESS);
		}
		return result;
	}
	
	/**
	 * 根据成品，得到使用范围
	 * @param part
	 * @author xucr
	 * @CreateDate 2020年11月3日
	 */
	public Map<String, String> getRangeValue(WTPart part) {
		/**
		 * 根据成品属性，匹配范围：
		 * 匹配一：消费品，产品归属(ProjectBelong)、显示技术类型（通用）(finishedGoodDisplayType)、CELL切割产地(CellCutOrigin)
		 * 匹配二：车载品，产品归属(ProjectBelong)、结构（structure）
		 * 匹配三：工业品，产品归属(ProjectBelong)、产品分级（productClassification）
		 */
		Map<String, String> rangeValue = null;
		try {
			if(null != part) {
				String projectBelong = (String) IBAUtil.getIBAValue(part, "ProjectBelong");
				//消费品
				String finishedGoodDisplayType = (String) IBAUtil.getIBAValue(part, "finishedGoodDisplayType");
				String cellCutOrigin = (String) IBAUtil.getIBAValue(part, "CellCutOrigin");
				rangeValue = QuantityConfig.getUsableRange(projectBelong, finishedGoodDisplayType, cellCutOrigin);
				if(null != rangeValue) {
					
				} else {
					//车载品
					String structure = (String) IBAUtil.getIBAValue(part, "structure");
					rangeValue = QuantityConfig.getUsableRange(projectBelong, structure, "");
					if(null != rangeValue) {
						
					} else {
						//工业品
						String productClassification = (String) IBAUtil.getIBAValue(part, "productClassification");
						rangeValue = QuantityConfig.getUsableRange(projectBelong, productClassification, "");
					}
				}
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		}
		return rangeValue;
	}
	
	/**
	 * 得到配置中所有的使用范围，用于报表搜索条件
	 * @return
	 * @author xucr
	 * @throws JSONException 
	 * @CreateDate 2020年11月6日
	 */
	public JSONObject getRangeValue() throws JSONException {
		Map<String, String> maps = QuantityConfig.getUsableRange();
		JSONObject ob = new JSONObject();
		JSONArray array = new JSONArray();
		if(null != maps && maps.size() > 0) {
			ob.put("status", "success");
			ob.put("message", "查询成功!");
			
			JSONObject m = null;
			for(Entry<String, String> set: maps.entrySet() ) {
				m = new JSONObject();
				m.put("key", set.getKey());
				m.put("value", set.getValue());
				array.put(m);
			}
			ob.put("data", array);
		} else {
			ob.put("status", "false");
			ob.put("message", "未查到！");
		}
		return ob;
	}
	
	/**
	 * 展示APL用量信息
	 * @param params
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月6日
	 */
	public JSONObject showAPLQuantity(JSONObject params) {
		List<APLQuantity> quantitys = AVLUtil.queryAPLQuantity(params);
		JSONArray array = new JSONArray();
		JSONObject result = null;
		try {
			if(null != quantitys && quantitys.size() > 0) {
				JSONObject obj = null;
				int i = 1;
				Map<String, String> map = AVLUtil.getIBARangeValue(); //得到八大使用范围的内部名称、 显示名称
				Map<String,String> maps = EnumerationUtil.getEnumerationValues("Level"); //得到等级枚举
				for(APLQuantity quantity : quantitys) {
					obj = new JSONObject();
					WTPartMaster master = (WTPartMaster) quantity.getPersistable().getObject();
					WTPart part = PartUtil.getWTPartByNumber(master.getNumber());
					String url = MaterielService.getUrlLink(part, false);
					obj.put("name", url);
					obj.put("number", master.getNumber());
					obj.put("MaterialType",TMUtil.conversion((String) IBAUtil.getIBAValue(part, "MaterialType")));
					obj.put("range", null != map.get(quantity.getRanges()) ? map.get(quantity.getRanges()) : quantity.getRanges());
					obj.put("quantity", quantity.getQuantity());
					obj.put("level", null != maps.get(quantity.getLevels()) ? maps.get(quantity.getLevels()) : quantity.getLevels());
					obj.put("status", quantity.getStatus());
					obj.put("owner", part.getCreatorFullName());
					obj.put("oid", TMUtil.obj2Oid(quantity));
					obj.put("id", i);
					array.put(obj);
					i++;
				}
			}
			result = ProjectUtil.respInfo(array, array.length());
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public static void test() throws WTException, JSONException {
		WTPart part = CoreUtil.getWTPartByNumberAndView("0000000132", "Design");
		List<Map<String, String>> list2 = new ArrayList<Map<String, String>>();
		getChildPart(part, list2, "3");
		String str = "";
		if(null != list2 && list2.size() > 0) {
			for(Map<String, String> m : list2) {
				
			}
		}
	}
	
	/**
	 * 递归获取子项，并累计各层级用量
	 * @param part
	 * @param map  key：子项， value：父项
	 * @param list2
	 * @param quantity
	 * @author xucr
	 * @CreateDate 2020年10月28日
	 */
	private static void getChildPart(WTPart part, List<Map<String, String>> list2, String quantity) {
		//参考ProjectUtil.getChildPart
		/**
		 * 成品  ERP用量2
		 * ----半成品      用量3
		 * ---------原材料1   用量1 -- 材料型号1     2x3x1
		 * ---------原材料2   用量2 -- 材料型号2     2x3x2
		 * ----原材料3   用量3      -- 材料型号1     2x3x3
		 *     
		 * --->   型号1： (2x3x1 + 2x3x3)  ；     型号2：  (2x3x2)
		 *     
		 *     
		 *     
		 * 封装成jsonarray
		 * 	quantity：从顶层到最底层的各个用量汇总
		 *  number：底层料号
		 *  type：底层料类型
		 *  main：底层料的替代料
		 * 
		 * [
		 * 	{quantity=3;;;0.2, number=0000000003, type=wt.part.WTPart|cn.tianma.RawMaterial}, 
		 * 	{quantity=3;;;2.0, number=0000000003, type=wt.part.WTPart|cn.tianma.RawMaterial, main=0000000001}, 
		 * ]
		 * 
		 * */
		try {
			WTPartStandardConfigSpec spec = PartCommandsUtil.getConfigSpecByView(part.getViewName());
			QueryResult qs = WTPartHelper.service.getUsesWTParts(part, spec);
			
			while (qs.hasMoreElements()) {
				Map<WTPart, WTPart> map = null; 
				Map<String, String> map2 = null;
				
				Map<WTPart, WTPart> cmap = null; 
				Map<String, String> cmap2 = null;
				Persistable[] apersistable = (Persistable[]) qs.nextElement();
				WTPartUsageLink link = (WTPartUsageLink) apersistable[0];
				/**
				 * WTPart childpart = BOMHelp.getPart(master.getNumber(), "", part.getViewName());
				 * 理论上，
				 * 物料转厂的时候，会将子项视图设定为一至，
				 * 但有特例，会单独添加料号，但无法控制视图，因此我们这里不能按照视图一样来查询
				 */
				WTPart childpart = (WTPart) apersistable[1];
				//特定替换部件
				WTArrayList c = (WTArrayList)WTPartHelper.service.getSubstituteLinksAnyAssembly(
						(WTPartMaster) childpart.getMasterReference().getObject());
				if(null != c && c.size() > 0) {
					//有替代料，加入替代料
					ObjectReference obj = null;
					for(int j = 0 ; j < c.size(); j++) {
						cmap = new HashMap<WTPart, WTPart>();
						cmap2 = new HashMap<String, String>();
						obj =  (ObjectReference) c.get(0);
						WTPartSubstituteLink ul = (WTPartSubstituteLink) obj.getObject();
						WTPartMaster wm = (WTPartMaster) ul.getRoleBObject();
						WTPart linkPart = BOMHelp.getPart(wm.getNumber(), "", childpart.getViewName());
						
						if(null != linkPart) {
							cmap.put(linkPart, part);
							String typeName = TypedUtility.getTypeIdentifier(linkPart).getTypename();
							cmap2.put("number", linkPart.getNumber());
							cmap2.put("quantity", quantity+ ";;;" + String.valueOf(ul.getQuantity().getAmount()));
							cmap2.put("main", childpart.getNumber());
							cmap2.put("type", typeName);
							list2.add(cmap2);
						}
					}
				}
				map = new HashMap<WTPart, WTPart>();
				map2 = new HashMap<String, String>();
				map.put(childpart, part);
				String typeName = TypedUtility.getTypeIdentifier(childpart).getTypename();
				map2.put("number", childpart.getNumber());
				map2.put("quantity", quantity+ ";;;" + String.valueOf(link.getQuantity().getAmount()));
				map2.put("type", typeName);
				
				list2.add(map2);
				getChildPart(childpart, list2, quantity+ ";;;" + String.valueOf(link.getQuantity().getAmount()));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private HSSFCellStyle initCellStyle(HSSFWorkbook wb, short color) {
		HSSFCellStyle cellStyle = wb.createCellStyle();
	    cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);//水平居中
	    cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//垂直居中
	    cellStyle.setWrapText(true);//设置Excel表格中\r\n换行
	    if(0 != color) {
	    	cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
			cellStyle.setFillForegroundColor(color);// 设置背景色
	    }
		return cellStyle;
	}
	
	/**
	 * 按搜索条件导出报表
	 * @param params
	 * @author xucr
	 * @throws IOException 
	 * @throws WTException 
	 * @throws JSONException 
	 * @CreateDate 2020年11月13日
	 */
	public String exportToExcel (JSONObject params) throws IOException, WTException, JSONException {
		List<APLQuantity> quantitys = AVLUtil.queryAPLQuantity(params);

		String domain = HTTP + "://" + HOSTNAME + File.separator + "Windchill";
		String folder = "TempExcel";
		WTProperties props = WTProperties.getLocalProperties();
		String filePath = props.getProperty("wt.codebase.location") + File.separator + "temp" + File.separator + folder + File.separator;
		File targerFile = new File(filePath);
		if(!targerFile.exists()) {
			targerFile.mkdirs();
		}
		String pathAndName = filePath + "APL用量报表.xls";
		String realPath = domain + File.separator + "temp" + File.separator + folder + File.separator + "APL用量报表.xls";
		
		//1.创建HSSFWorkbook,对应一个excel
		HSSFWorkbook wb = new HSSFWorkbook();
		
		//2.在workbook中创建一个sheet，对应excel中的sheet
		HSSFSheet sheet = wb.createSheet("APL报表数据");
		
		//3.在sheet中添加表头第0行
		HSSFRow row = sheet.createRow(0);
		
		//4.创建单元格，并设置值表头 设置表头居中
	    HSSFCellStyle cellStyle = wb.createCellStyle();
	    cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);//设置居中
	    
 		// 创建标题
	 	int num = 0;
	 	HSSFCell cell = null;
 		for (String title : map.keySet()) {
 			cell = row.createCell(num);
 			cell.setCellValue(map.get(title).split(SPLITVALUE)[0]);
 			cell.setCellStyle(cellStyle);
 			num++;
 		}
 		
 		//创建内容
 		HSSFCell cell2 = null;
 		Map<String, String> ranges = AVLUtil.getIBARangeValue();
 		Map<String,String> maps = EnumerationUtil.getEnumerationValues("Level"); //得到等级枚举
 		for(int i =0; i<quantitys.size(); i++) {
 			HSSFRow tempRow = sheet.createRow(i+1);
 			APLQuantity quantity = quantitys.get(i);
 			WTPartMaster master = (WTPartMaster) quantity.getPersistable().getObject();
 			WTPart part = PartUtil.getWTPartByNumber(master.getNumber());
 			int j = 0;
 			String cellValue = "";
 			for(String key : map.keySet()) {
 				cell2 = tempRow.createCell(j);
 				if(j == 0) {//序号
 					cellValue = String.valueOf(i + 1);
 				} else if(j == 3) {//材料型号
 					cellValue = TMUtil.conversion((String) IBAUtil.getIBAValue(part, "MaterialType"));
 				} else {
 					String value = map.get(key);
 					if(StringUtils.isNotEmpty(value)) {
 						String classType = value.split(SPLITVALUE)[1];
 						if(WTPART.equals(classType)) {
 							cellValue = (String) AVLUtil.getAttributeObjValForReflex(part, key);
 						} else if(APLQUANTITY.equals(classType)) {
 							cellValue = (String) AVLUtil.getAttributeObjValForReflex(quantity, key);
 							//使用范围
 	 						if("getRanges".equals(key)) {
 	 							cellValue = ranges.get(cellValue);
 	 						} else if("getLevels".equals(key)) {
 	 							cellValue = maps.get(cellValue);
 	 						}
 						}
 					}
 				}
 				cell2.setCellValue(cellValue);
 				cell2.setCellStyle(cellStyle);
 				j++;
 			}
 			//调整每一列宽度自适应
 			sheet.autoSizeColumn((short)i);
 		}
        FileOutputStream os = new FileOutputStream(pathAndName);
        wb.write(os);
		os.flush();
		os.close();
		return realPath;
	}
}
 